/* 
 * File:   misc.h
 * Author: filipp
 *
 * Created on March 15, 2010, 4:34 PM
 */

#ifndef _MISC_H
#define	_MISC_H

#include <math.h>
#include <vector>
#include <algorithm>



template <typename T>
class autoInitPtr{
public:
	autoInitPtr() : ptr(NULL) {}
	autoInitPtr(T* p) : ptr(p) {}
	autoInitPtr(const autoInitPtr<T>& aipt) : ptr(aipt.ptr) {}
	autoInitPtr<T>& operator=(const autoInitPtr<T>& aipt) { ptr=aipt.ptr; }
	T* ptr;
};
template <typename T>
T& operator*(const autoInitPtr<T>& aipt){ return *aipt.ptr; }
template <typename T>
autoInitPtr<T>& operator+=(autoInitPtr<T>& aipt, int i) { aipt.ptr+=i; return aipt; }
template <typename T>
autoInitPtr<T>& operator-=(autoInitPtr<T>& aipt, int i) { aipt.ptr-=i; return aipt; }
template <typename T>
autoInitPtr<T> operator+(const autoInitPtr<T>& aipt, int i) { return aipt.ptr + i; }
template <typename T>
autoInitPtr<T> operator-(const autoInitPtr<T>& aipt, int i) { return aipt.ptr - i; }
template <typename T>
int operator-(const autoInitPtr<T>& l, const autoInitPtr<T>& r) { return l.ptr-r.ptr; }

template <typename T>
class smoothTracer{
public:
	smoothTracer(size_t smoothness) : data(new T[smoothness]), s(smoothness),
		c(0) {
		for(size_t i=0; i<s; ++i)
			data[i]=0;
	}
	void nextValue(const T& value){
		data[c++]=value;
		if(c>=s)
			c=0;
	}
	T average(){
		T accum=0;
		for(size_t i=0; i<s; ++i)
			accum+=data[i];
		accum/=s;
		return accum;
	}
private:
	T* data;
	size_t s;
	size_t c;
};

enum UserEventType{
	USER_NO_EVENT=0,
	USER_SCREEN_REFRESH_REQUEST,
	USER_GAME_REFRESH_REQUEST
};

class vec2f;

class vec2i{
public:
	vec2i(int nx=0, int ny=0);
	vec2i(const vec2i& other);
	vec2i(const vec2f& other);
	vec2i& operator=(const vec2i& other);
	vec2i& operator=(const vec2f& other);
	int dot(const vec2i& r) const;
	int cross(const vec2i& r) const;
	float magnitude() const;
	vec2f normalized() const;
	int x;
	int y;
};
vec2i& operator+=(vec2i& l, const vec2i& r);
vec2i& operator-=(vec2i& l, const vec2i& r);
vec2i& operator*=(vec2i& l, const vec2i& r);
vec2i& operator/=(vec2i& l, const vec2i& r);
vec2i& operator*=(vec2i& l, int r);
vec2i& operator/=(vec2i& l, int r);
vec2i operator+(const vec2i& l, const vec2i& r);
vec2i operator-(const vec2i& l, const vec2i& r);
vec2i operator*(const vec2i& l, const vec2i& r);
vec2i operator/(const vec2i& l, const vec2i& r);
vec2i operator*(const vec2i& l, int r);
vec2i operator/(const vec2i& l, int r);
vec2i operator*(int l, const vec2i& r);
vec2i operator-(const vec2i& r);


class vec2f{
public:
	vec2f(float nx=0, float ny=0);
	vec2f(const vec2f& other);
	vec2f(const vec2i& other);
	vec2f& operator=(const vec2f& other);
	vec2f& operator=(const vec2i& other);
	float dot(const vec2f& r) const;
	float cross(const vec2f& r) const;
	float magnitude() const;
	vec2f normalized() const;
	float x;
	float y;
};
vec2f& operator+=(vec2f& l, const vec2f& r);
vec2f& operator-=(vec2f& l, const vec2f& r);
vec2f& operator*=(vec2f& l, const vec2f& r);
vec2f& operator/=(vec2f& l, const vec2f& r);
vec2f& operator*=(vec2f& l, float r);
vec2f& operator/=(vec2f& l, float r);
vec2f operator+(const vec2f& l, const vec2f& r);
vec2f operator-(const vec2f& l, const vec2f& r);
vec2f operator*(const vec2f& l, const vec2f& r);
vec2f operator/(const vec2f& l, const vec2f& r);
vec2f operator*(const vec2f& l, float r);
vec2f operator/(const vec2f& l, float r);
vec2f operator*(float l, const vec2f& r);
vec2f operator-(const vec2f& r);

//this function assumes that 1 point is equal to one unit distance of path
void pathTrace(const vec2f& path, std::vector<vec2i>& traversedPoints);
void pointsInCircle(float magnitude, std::vector<vec2i>& occupiedPoints);





//Unit vectors by octant and by axis
//these are in cartesian coordinates, Y points up
const vec2f		UNIT_0(1.0f,0.0f); //right
const vec2f		UNIT_X=UNIT_0; //right
const vec2f		UNIT_1=vec2f(1.0f,1.0f).normalized(); //up right
const vec2f		UNIT_2(0.0f,1.0f); //up
const vec2f		UNIT_Y=UNIT_2; //up
const vec2f		UNIT_3=vec2f(-1.0f,1.0f).normalized(); //up left
const vec2f		UNIT_4=-UNIT_0; //left
const vec2f		UNIT_5=-UNIT_1; //down left
const vec2f		UNIT_6=-UNIT_2; //down
const vec2f		UNIT_7=-UNIT_3; //down right

//counterclockwise vectors. UNIT is a float unit vector, OCTANT_MAP is for coordinate grid
const vec2f UNIT[]={UNIT_0, UNIT_1, UNIT_2, UNIT_3, UNIT_4, UNIT_5, UNIT_6, UNIT_7};
const vec2i OCTANT_MAP[]={vec2i(1,0),vec2i(1,1),vec2i(0,1),vec2i(-1,1),vec2i(-1,0),vec2i(-1,-1),vec2i(0,-1),vec2i(1,-1)};

const float SQ2 = sqrtf(2.0f);
const float RMS = 1.0/SQ2;
#endif	/* _MISC_H */

